home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
byt87ibm.arc
/
SAGAN.ARC
/
MOUSESYS.ASM
< prev
Wrap
Assembly Source File
|
1987-06-17
|
7KB
|
255 lines
;
ASSUME CS:CSEG, DS:CSEG, ES:NOTHING, SS:NOTHING
;
SERIAL EQU 14H
MSDOS EQU 21H
;
;
; This is the main entry point
; all driver routines take the function call number in BX
;
; function 0 = initialize mouse
; function 1 = return button status
; function 2 = return relative motion
; function 3 = de-initialize mouse
; function 4 = return current serial port
;
; Normally this would be a far procedure but to avoid getting into
; all the intricasies of loading and calling drivers I've converted
; ENTRY to a near procedure and combined it with the sample program.
;
ENTRY PROC NEAR
CLD ; go in the forward direction
PUSH DS ; save callers segment
PUSH CS ; make this segment addressable
POP DS
SHL BX,1 ; point to routine
CALL ROUTINES[BX] ; and call it through table
POP DS ; restore users segment
RET ; return far to caller
ENTRY ENDP
;
DB 'Mouse systems',00 ; name
;
ROUTINES LABEL WORD
DW ISERIAL ; function 0 = initialize mouse
DW BUTTONSTAT ; function 1 = return button status
DW MOTIONCOUNT ; function 2 = return relative motion
DW DSERIAL ; function 3 = de-initialize mouse
DW GSERIAL ; function 4 = return current serial port
DW RETADR ; function 5 = reserved
DW RETADR ; function 6 = reserved
DW RETADR ; function 7 = reserved
;
COMNUM DW 00 ; com#
;
NEWX DW 00 ; New x coordinate
NEWY DW 00 ; New y coordinate
XACCUM DW 0 ; Old x coordinate
YACCUM DW 0 ; Old y coordinate
BSTAT DB 07H ; button status byte
CPORT DW 03F8H ; communications port address
PCOUNT DB 0 ; packet counter
IMSK DB 0EFH ; interrupt mask
;
; This is the heart of the code.
; The serial interrupt handler. This code catches serial bytes and maintains
; a running total of delta x and delta y values.
;
;
ISR:
STI ; Ints back on
PUSH AX ; Save all registers used
PUSH BX
PUSH DX
PUSH DS
PUSH CS
POP DS ; make Code SEGment addressable
MOV DX,CPORT ; get port address
ADD DX,5 ; Status
IN AL,DX ; Read status
MOV AH,AL ; Save in Ah
SUB DX,5 ; back to data port address
IN AL,DX ; get byte from port
AND AH,01EH ; mask error bits of status
JNZ ISR3 ; jmp if error
;
; Jump if an error has occured on the serial line! most likely an overrun
; error caused by interrupts cleared for long periods of time.
; This will be handled simply by clearing the packet counter.
;
ISR2:
CMP PCOUNT,0 ; Is this the first byte of packet ?
JNE ISR25 ; no so accumulate.
MOV AH,AL ; it is the first byte so check certain
AND AH,0F8H ; bits to se if we're in sync with the
CMP AH,080H ; data stream. If we're not then
JNZ ISR4 ; we'll just return
MOV BSTAT,AL ; we are in sync so stuff button status byte
ISR25:
MOV BL,PCOUNT ; get packet counter
INC PCOUNT ; increment for next serial interrupt
OR BL,BL ; if it's zero we're done
JZ ISR4
;
CBW ; Convert delta byte to delta word
TEST BL,1 ; Check if odd or even. odd = x values
JZ ADDY ; even = y values
ADD XACCUM,AX ; add to running x accumulator
JMP SHORT ISR29
ADDY:
ADD YACCUM,AX ; or add to running y accumulator
ISR29:
CMP BL,4 ; end of packet
JB ISR4 ; no
ISR3:
MOV PCOUNT,0 ; yes, so reset packet counter
ISR4:
CLI
MOV AL,020H ; must issue EOI
OUT 020H,AL
POP DS
POP DX
POP BX
POP AX ; Restore registers
IRET ; and return from interrupt
;
; This table maps button values into ones appropriate for returning
; to application
;
BUTMAP DB 07,03,05,01,06,02,04,00
;
; This routine returns button status = ax
; a 1 bit indicates button presses
;
BUTTONSTAT:
PUSH BX
MOV AL,BSTAT
AND AX,7
MOV BX,OFFSET BUTMAP ; convert to Microsoft format
XLAT
POP BX
RETADR:
RET
;
; Motion Count routine
; on entry:
; Ax=cursor x,Bx=cursor y (Ignored by this driver)
; on exit:
; Ax=delta x,Bx=delta y
;
MOTIONCOUNT:
CALL QREADPACKET ; Read a packet
MOV BX,NEWY ; return y coordinates
NEG BX ; positive coordinate move down the screen
MOV AX,NEWX ; return x
RET
;
; clean up the serial port interrupts and masks
;
DSERIAL:
CLI
IN AL,021H ; Read interupt mask
MOV AH,IMSK ; clear appropriate int
NOT AH ; by setting bits
OR AL,AH
OUT 021H,AL ; write it out
MOV DX,CPORT ; get port address
ADD DX,3 ; line control register
IN AL,DX ; fetch it
AND AL,07FH ; set low to access interrupt
OUT DX,AL ; enable register
SUB DX,2 ; point at interrupt enable register
SUB AL,AL ; clear
OUT DX,AL ; it
ADD DX,3 ; and clear
OUT DX,AL ; modem control register
STI ; finished
RET
;
GSERIAL:
MOV AX,COMNUM ; returns com#
INC AX
RET
;
; This code intializes the mouse systems serial mouse
; it takes the com number in Ax (1 = com1 2 = com2)
;
ISERIAL PROC NEAR
PUSH CX
DEC AX
MOV COMNUM,AX ; Save com#
MOV DX,AX
MOV AX,087H ; 12K BAUD
INT SERIAL ; let bios initialize baud rate and stuff
;
PUSH BX
PUSH DX
PUSH CS
MOV AX,040H ; point at bios data segment
MOV DS,AX
MOV BX,DX
SHL BX,1
MOV DX,ZERO[BX] ; Get port address at 40:0 or 40:2
POP DS
MOV CPORT,DX ; save it
CLI
MOV DX,OFFSET ISR ; stick the serial interrupt handler
MOV AL,00CH ; in either Int 0Ch, or 0Bh
MOV AH,BYTE PTR COMNUM
AND AH,1 ; only 2 Interrupts available
SUB AL,AH
MOV AH,025H ; set interrupt request
INT MSDOS
;
IN AL,021H ; mask the interrup controller
MOV AH,0EFH
CMP COMNUM,0
JZ ISERIAL2
MOV AH,0F7H
ISERIAL2:
MOV IMSK,AH ; Save for later
AND AL,AH
OUT 021H,AL
;
MOV DX,CPORT ; get port address
ADD DX,3 ; Line control register
IN AL,DX
AND AL,07FH ; make interrupt enable register
OUT DX,AL ; Addressable
JMP $+2
SUB DX,2 ; Point at it
MOV AL,1 ; set the data available int
OUT DX,AL
ADD DX,3 ; Modem control register
MOV AL,08 ; set it
OUT DX,AL
STI
MOV DX,CPORT
IN AL,DX ; Clear receive buffer
POP DX
POP BX
POP CX
MOV AL,-1 ; mouse available.
RET
ISERIAL ENDP
;
;
QREADPACKET:
QR1:
CLI
;
NOP
MOV AX,XACCUM ; get x accumulator
MOV NEWX,AX ; move to new delta x
MOV AX,YACCUM ; get y
MOV NEWY,AX ; to new y
SUB BX,BX
MOV XACCUM,BX ; clear
MOV YACCUM,BX ; accumulators
;
STI
QREXIT:
RET
;